#include "ParserMainWindow.h"

/* To do:
    Liaison statique
    About project
    PB Splash
    Palette tree
*/

/**************************************************************************/
/**************************************************************************/
ParserMainWindow::ParserMainWindow()
{
    setupUi(this);
    inputPath = QString();
    outputPath = QString();

    splash = new QSplashScreen(QPixmap(":/images/univSplash"));//, Qt::WindowStaysOnTopHint);
    // splash->finish(treeView);
    // splash->show();
    // splash->showMessage("Veuillez patienter pendant que l'application analyse vos disques ...",Qt::AlignBottom | Qt::AlignHCenter);

    settings = new SettingsDial();
    browser = new BrowserWindow();
    error = new ErrorDial();
    outputDial = new OutputDial();
    aboutParserDial = new AboutParserDial();

    model = new QDirModel();

    treeView = new DropTreeView(groupBox_2);
    treeView->setGeometry(QRect(10,20,421,231));

    treeView->setModel(model);
    treeView->hideColumn(2);
    treeView->hideColumn(3);
    treeView->setColumnWidth(0,310);

    browser->treeView->setModel(model);
    browser->treeView->hideColumn(2);
    browser->treeView->hideColumn(3);
    browser->treeView->setColumnWidth(0,310);

    highlighter = new SyntaxHighlighter(outputDial->textEdit->document());

    outputstyleChanged();
    makeConnections();
    // emit dirModelCreated();
}

/**************************************************************************/
/**************************************************************************/
void ParserMainWindow::makeConnections()
{
    QObject function;

    //(*prtToQtConnect)(this,SIGNAL(dirModelCreated()),this,SLOT(show()), Qt::AutoConnection);

    // How to quit application.
    actionQuitter->setShortcut(QKeySequence("Ctrl+Q"));

    (*prtToQtConnect)(actionQuitter,SIGNAL(triggered()),qApp,SLOT(quit()), Qt::AutoConnection);
    (*prtToQtConnect)(pushButton_3,SIGNAL(clicked()),qApp,SLOT(quit()), Qt::AutoConnection);

    // One click on "Preferences" makes settings dialog pop up.
    actionPreferences->setShortcut(QKeySequence("Ctrl+P"));
    (*prtToQtConnect)(actionPreferences,SIGNAL(triggered()),settings,SLOT(show()), Qt::AutoConnection);

    // CTRL+H to display 'about Qt' window.
    // actionA_propos_de_Qt->setShortcut(QKeySequence("Ctrl+H"));
    (*prtToQtConnect)(actionA_propos_de_Qt,SIGNAL(triggered()),qApp,SLOT(aboutQt()), Qt::AutoConnection);

    // One click on 'browse' button opens a browse window.
    (*prtToQtConnect)(pushButton,SIGNAL(clicked()),browser,SLOT(show()), Qt::AutoConnection);

    // CTRL+R to display last analysis' result.
    actionResultat->setShortcut(QKeySequence("Ctrl+L"));
    (*prtToQtConnect)(actionResultat,SIGNAL(triggered()),outputDial,SLOT(show()), Qt::AutoConnection);

    (*prtToQtConnect)(actionA_propos_du_parser,SIGNAL(triggered()),aboutParserDial,SLOT(show()), Qt::AutoConnection);

    // One click on 'analyze' button calls parse methode i.e. start analysis.
    (*prtToQtConnect)(pushButton_2,SIGNAL(clicked()),this,SLOT(parse()), Qt::AutoConnection);

    // One click on 'clear' button clears all GUI fields i.e. intput & output paths.
    (*prtToQtConnect)(pushButton_4,SIGNAL(clicked()),this,SLOT(clear()), Qt::AutoConnection);

    // One click on one or another check box changes application output style.
    // Screen output type.
    (*prtToQtConnect)(checkBox,SIGNAL(clicked()),this,SLOT(outputstyleChanged()), Qt::AutoConnection);

    // File output type.
    (*prtToQtConnect)(checkBox_2,SIGNAL(clicked()),this,SLOT(outputstyleChanged()), Qt::AutoConnection);

    (*prtToQtConnect)(checkBox_2,SIGNAL(clicked(bool)),lineEdit,SLOT(setEnabled(bool)), Qt::AutoConnection);
    (*prtToQtConnect)(checkBox_2,SIGNAL(clicked(bool)),pushButton,SLOT(setEnabled(bool)), Qt::AutoConnection);
    (*prtToQtConnect)(checkBox_2,SIGNAL(clicked(bool)),label_2,SLOT(setEnabled(bool)), Qt::AutoConnection);

    (*prtToQtConnect)(this,SIGNAL(raiseError(QString)),error,SLOT(displayError(QString)), Qt::AutoConnection);

    // Set of input & output paths.
    (*prtToQtConnect)(treeView,SIGNAL(clicked(QModelIndex)),this,SLOT(inputIndexChanged(QModelIndex)), Qt::AutoConnection);

    // To intercept file data when drag and drop is used to set input file.
    (*prtToQtConnect)(treeView,SIGNAL(fileReceived(QString)),this,SLOT(inputFileReceived(QString)), Qt::AutoConnection);

    (*prtToQtConnect)(browser->treeView,SIGNAL(clicked(QModelIndex)),this,SLOT(browserOutputIndexChanged(QModelIndex)), Qt::AutoConnection);
    (*prtToQtConnect)(browser,SIGNAL(outputPathChanged(QString)),this,SLOT(outputPathChanged(QString)), Qt::AutoConnection);

    // (*prtToQtConnect)(lineEdit,SIGNAL(editingFinished()),this,SLOT(refreshUI()), Qt::AutoConnection);
}

/**************************************************************************/
/**************************************************************************/
void ParserMainWindow::inputFileReceived(QString path)
{
    QModelIndex index = model->index(path);
    inputIndexChanged(index);
}

/**************************************************************************/
/**************************************************************************/
void ParserMainWindow::inputIndexChanged(QModelIndex index)
{
    treeView->setCurrentIndex(index);

    if (!model->isDir(index))
        {inputPath = model->filePath(index);}

    else
        {inputPath.clear();}

    label->setText(inputPath);
    refreshUI();
}

/**************************************************************************/
/**************************************************************************/
void ParserMainWindow::browserOutputIndexChanged(QModelIndex index)
{
    if (model->isDir(index))
        {
            browser->outputPath = model->filePath(index);
            browser->pushButton->setEnabled(true);
        }

    else
        {
            browser->outputPath.clear();
            browser->pushButton->setEnabled(false);
        }

    browser->label->setText(browser->outputPath);
}

/**************************************************************************/
/**************************************************************************/
void ParserMainWindow::outputPathChanged(QString path)
{
    outputPath = path;
    label_2->setText(path);
    refreshUI();
}

/**************************************************************************/
/**************************************************************************/
void ParserMainWindow::outputstyleChanged()
{
    // Screen output is checked.
    if (checkBox->isChecked())
    {
        // File output is checked.
        if (checkBox_2->isChecked())
        {
            output = screen_file;
            // statusbar->showMessage(("Type de sortie : Ecran & Fichier"));
        }

        else
        {
            // File output is NOT checked.
            output = screen;
            // statusbar->showMessage(("Type de sortie : Ecran"));
        }
    }

    // Screen output is NOT checked.
    // File output is checked.
    else if (checkBox_2->isChecked())
    {
        output = file;
        // statusbar->showMessage(("Type de sortie : Fichier"));
    }

    else
    {
        output = none;
        statusbar->showMessage(("Attention : Vous devez choisir un type de sortie."));
    }
    refreshUI();
}

/**************************************************************************/
/**************************************************************************/
void ParserMainWindow::clear()
{
    outputDial->textEdit->clear();

    outputPath.clear();
    inputPath.clear();
    browser->outputPath.clear();

    label->clear();
    label_2->clear();
    browser->label->clear();

    pushButton_2->setEnabled(false);
    browser->pushButton->setEnabled(false);

    treeView->reset();
    browser->treeView->reset();
}

/**************************************************************************/
/**************************************************************************/
void ParserMainWindow::refreshUI()
{
    switch (output)
    {
        // Check if input path is valid.
        case screen : if (!inputPath.isEmpty())
                            {pushButton_2->setEnabled(true); return;}
                      break;

        // Check is an output type is selected.
        case none : pushButton_2->setEnabled(false);
                    break;

        // File + screen_file output type.
        // Check input path AND output path.
        default :
                  if ( !(lineEdit->text().isEmpty()) && !(inputPath.isEmpty()) )
                        {pushButton_2->setEnabled(true); return;}
                  break;
    }
    pushButton_2->setEnabled(false);
}

/**************************************************************************/
/**************************************************************************/
void ParserMainWindow::parse()
{
    char scriptFileName[settings->scriptFile.size()];
    strcpy(scriptFileName, settings->scriptFile.toStdString().c_str());

    char *my_argv[] = {"",scriptFileName};
    my_perl = perl_alloc();
    perl_construct(my_perl);

    perl_parse(my_perl,NULL,2,my_argv,(char **)NULL);
    // perl_run(my_perl);

    QString realOutput;
    if (output != file && output != screen_file)
    {
        realOutput = "";
    }

    else {realOutput = QString(outputPath).append("/").append(lineEdit->text()).append(QString(".")).append(settings->outputExtension);}

    splash->show();
    splash->showMessage("Veuillez patienter pendant que l'application analyse votre fichier ...",Qt::AlignBottom | Qt::AlignHCenter);
    // splash->showMessage(realOutput,Qt::AlignBottom | Qt::AlignHCenter);

    if (callParsingScript(inputPath.toStdString().c_str(),realOutput.toStdString().c_str()) == -1)
    {
        outputDial->textEdit->clear();
        emit raiseError(QString("Une erreur s'est produite lors de l'analyse du fichier\n").append(inputPath));
    }

    perl_destruct(my_perl);
    perl_free(my_perl);
    realOutput.clear();
    // delete scriptFileName;
}

/**************************************************************************/
/**************************************************************************/
int ParserMainWindow::callParsingScript(const char* inputFile, const char* outputFile)
{
    dSP;                                  // Declare and initialize a local copy of the Perl stack pointer.
    ENTER;
    SAVETMPS;
    PUSHMARK(SP);
    XPUSHs(sv_2mortal(newSVpv(inputFile,0))); // Intput file name is put on top of the stack.
    XPUSHs(sv_2mortal(newSVpv(outputFile,0)));// Intput file name is put on top of the stack.
    PUTBACK;

    char scriptSubName[settings->scriptSubRoutine.size()];
    strcpy(scriptSubName, settings->scriptSubRoutine.toStdString().c_str());

    int returnValuesCount = (call_pv(scriptSubName, G_SCALAR));
    if (returnValuesCount != 1)
    {
        // delete scriptSubName;
        return -1;
    }
    SPAGAIN;

    SV *s;
    s = POPs;
    char* resultString = SvPV_nolen(s);
    outputDial->textEdit->setText(QString(resultString));

    if (output == screen || output == screen_file)
        {
            outputDial->show();
            splash->hide();
        }

    PUTBACK;
    FREETMPS;
    LEAVE;
    // delete scriptSubName;
    return 0;
}

